﻿/*
 * Copyright 2012 Rene Prost, Registrite ja Infosüsteemide Keskus 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Services.Description;
using System.Xml;
using System.Xml.Schema;
using Xtee.Core.Services.Description;
using MessagePart = System.Web.Services.Description.MessagePart;

namespace Xtee.Core
{
    public static class ServiceDescriptionExtensions
    { 
        public static XmlLinkedNode GetXteeExtensionElement(this ServiceDescriptionFormatExtensionCollection from,string name)
        {
            foreach (var node in from.OfType<XmlLinkedNode>())
            {
                if (node.LocalName == name && (node.NamespaceURI == "http://x-road.eu/xsd/xroad.xsd"))
                {
                    return node;
                }
            }

            return null;
        }

        public static void EnsureInTargetNamespace(this ServiceDescription description, XmlQualifiedName referenced, string what, string @in, string name)
        { 
            if (referenced.Namespace != description.TargetNamespace)
            {
                throw new ServiceDescriptionException("{0} referenced from {1} '{2}' should be in wsdl target namespace", what, @in, name); 
            } 
        }

        public static bool IsSoapEncArray(this XmlSchemaObject type)
        {
            var complexType = type as XmlSchemaComplexType;
            if (complexType != null &&
                complexType.ContentModel != null &&
                complexType.ContentModel.Content is XmlSchemaComplexContentRestriction)
            {
                var restr =
                    ((XmlSchemaComplexContentRestriction)complexType.ContentModel.Content);
                if (restr.BaseTypeName.Namespace.TrimEnd('/') == "http://schemas.xmlsoap.org/soap/encoding" &&
                    restr.BaseTypeName.Name == "Array")
                {
                    return true;
                }
            }

            return false;
        }

        public static bool IsArray(this XmlSchemaObject type)
        {
            var element = type as XmlSchemaElement;
            
            var complexType = element != null? element.ElementSchemaType as XmlSchemaComplexType : type as XmlSchemaComplexType;

            if (complexType != null)
            {
                var sequnceParticle = complexType.ContentTypeParticle as XmlSchemaSequence;

                if (sequnceParticle != null && sequnceParticle.Items.Count==1)
                {
                    var itemElement = sequnceParticle.Items[0] as XmlSchemaElement;

                    if (itemElement != null && (itemElement.MaxOccurs > 1 || itemElement.MinOccurs > 1))
                        return true;
                }
            }

            return false;
        }

        public static bool CanGenerateCode(this XmlSchemaObject obj)
        {
            if (obj is XmlSchemaComplexType && !obj.IsArray()) 
            {
                return true;
            }
            if (obj is XmlSchemaSimpleType)
            {
                return true;
            }
            return false;
        }

        public static List<SoapHeaderBinding> GetHeaderBindings(this ServiceDescriptionFormatExtensionCollection collection, XmlQualifiedName targetNameSpace)
        {
            var mimeMultipartRelatedBindings = collection.OfType<MimeMultipartRelatedBinding>().ToList();

            if (mimeMultipartRelatedBindings.Any())
            {
                if (mimeMultipartRelatedBindings.Count > 1)
                    throw new Exception("Expected only one multipartRelated binding.");
                var mimeMultipartRelatedBinding = mimeMultipartRelatedBindings.First();
                var part = mimeMultipartRelatedBinding.Parts.Cast<MimePart>().First();
                
                return part.Extensions.OfType<XmlElement>().Where(x=>x.LocalName=="header") //häkk, millegipärast ei ole listis SoapHeaderBindinguna elemendid
                    .Select(x=>new SoapHeaderBinding
                    {
                        Message = new XmlQualifiedName(x.Attributes.OfType<XmlAttribute>().First(attribute=> attribute.LocalName=="message").Value.Split(':')[1], targetNameSpace.Namespace),
                        Part = x.Attributes.OfType<XmlAttribute>().First(attribute => attribute.LocalName == "part").Value,
                        Use = SoapBindingUse.Literal
                    }).ToList();
            }

            return collection.OfType<SoapHeaderBinding>().ToList();

        }
    }
}